home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / ftp / ftp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-18  |  31.9 KB  |  1,647 lines

  1. /*
  2.  * Copyright (c) 1985, 1989 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. static char sccsid[] = "@(#)ftp.c    5.26 (Berkeley) 3/21/89";
  20. #endif /* not lint */
  21.  
  22. #include <sys/param.h>
  23. #include <sys/stat.h>
  24. #include <sys/ioctl.h>
  25. #include <sys/socket.h>
  26. #include <sys/time.h>
  27. #include <sys/file.h>
  28.  
  29. #include <netinet/in.h>
  30. #include <arpa/ftp.h>
  31. #include <arpa/telnet.h>
  32.  
  33. #include <stdio.h>
  34. #include <signal.h>
  35. #include <errno.h>
  36. #include <netdb.h>
  37. #include <fcntl.h>
  38. #include <pwd.h>
  39. #include <varargs.h>
  40.  
  41. #include "ftp_var.h"
  42.  
  43. struct    sockaddr_in hisctladdr;
  44. struct    sockaddr_in data_addr;
  45. int    data = -1;
  46. int    abrtflag = 0;
  47. int    ptflag = 0;
  48. int    connected;
  49. struct    sockaddr_in myctladdr;
  50. uid_t    getuid();
  51. off_t    restart_point = 0;
  52.  
  53. FILE    *cin, *cout;
  54. FILE    *dataconn();
  55.  
  56. char *
  57. hookup(host, port)
  58.     char *host;
  59.     int port;
  60. {
  61.     register struct hostent *hp = 0;
  62.     int s,len;
  63.     static char hostnamebuf[80];
  64.  
  65.     bzero((char *)&hisctladdr, sizeof (hisctladdr));
  66.     hisctladdr.sin_addr.s_addr = inet_addr(host);
  67.     if (hisctladdr.sin_addr.s_addr != -1) {
  68.         hisctladdr.sin_family = AF_INET;
  69.         (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
  70.     } else {
  71.         hp = gethostbyname(host);
  72.         if (hp == NULL) {
  73.             fprintf(stderr, "ftp: %s: ", host);
  74.             herror((char *)NULL);
  75.             code = -1;
  76.             return((char *) 0);
  77.         }
  78.         hisctladdr.sin_family = hp->h_addrtype;
  79.         bcopy(hp->h_addr_list[0],
  80.             (caddr_t)&hisctladdr.sin_addr, hp->h_length);
  81.         (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
  82.     }
  83.     hostname = hostnamebuf;
  84.     s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
  85.     if (s < 0) {
  86.         perror("ftp: socket");
  87.         code = -1;
  88.         return (0);
  89.     }
  90.     hisctladdr.sin_port = port;
  91.     while (connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) {
  92.         if (hp && hp->h_addr_list[1]) {
  93.             int oerrno = errno;
  94.  
  95.             fprintf(stderr, "ftp: connect to address %s: ",
  96.                 inet_ntoa(hisctladdr.sin_addr));
  97.             errno = oerrno;
  98.             perror((char *) 0);
  99.             hp->h_addr_list++;
  100.             bcopy(hp->h_addr_list[0],
  101.                  (caddr_t)&hisctladdr.sin_addr, hp->h_length);
  102.             fprintf(stdout, "Trying %s...\n",
  103.                 inet_ntoa(hisctladdr.sin_addr));
  104.             (void) close(s);
  105.             s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
  106.             if (s < 0) {
  107.                 perror("ftp: socket");
  108.                 code = -1;
  109.                 return (0);
  110.             }
  111.             continue;
  112.         }
  113.         perror("ftp: connect");
  114.         code = -1;
  115.         goto bad;
  116.     }
  117.     len = sizeof (myctladdr);
  118.     if (getsockname(s, (char *)&myctladdr, &len) < 0) {
  119.         perror("ftp: getsockname");
  120.         code = -1;
  121.         goto bad;
  122.     }
  123.     cin = fdopen(s, "r");
  124.     cout = fdopen(s, "w");
  125.     if (cin == NULL || cout == NULL) {
  126.         fprintf(stderr, "ftp: fdopen failed.\n");
  127.         if (cin)
  128.             (void) fclose(cin);
  129.         if (cout)
  130.             (void) fclose(cout);
  131.         code = -1;
  132.         goto bad;
  133.     }
  134.     if (verbose)
  135.         printf("Connected to %s.\n", hostname);
  136.     if (getreply(0) > 2) {     /* read startup message from server */
  137.         if (cin)
  138.             (void) fclose(cin);
  139.         if (cout)
  140.             (void) fclose(cout);
  141.         code = -1;
  142.         goto bad;
  143.     }
  144. #ifdef SO_OOBINLINE
  145.     {
  146.     int on = 1;
  147.  
  148.     if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on))
  149.         < 0 && debug) {
  150.             perror("ftp: setsockopt");
  151.         }
  152.     }
  153. #endif SO_OOBINLINE
  154.  
  155.     return (hostname);
  156. bad:
  157.     (void) close(s);
  158.     return ((char *)0);
  159. }
  160.  
  161. login(host)
  162.     char *host;
  163. {
  164.     char tmp[80];
  165.     char *user, *pass, *acct, *getlogin(), *getpass();
  166.     int n, aflag = 0;
  167.  
  168.     user = pass = acct = 0;
  169.     if (ruserpass(host, &user, &pass, &acct) < 0) {
  170.         code = -1;
  171.         return(0);
  172.     }
  173.     if (user == NULL) {
  174.         char *myname = getlogin();
  175.  
  176.         if (myname == NULL) {
  177.             struct passwd *pp = getpwuid(getuid());
  178.  
  179.             if (pp != NULL)
  180.                 myname = pp->pw_name;
  181.         }
  182.         printf("Name (%s:%s): ", host, myname);
  183.         (void) fgets(tmp, sizeof(tmp) - 1, stdin);
  184.         tmp[strlen(tmp) - 1] = '\0';
  185.         if (*tmp == '\0')
  186.             user = myname;
  187.         else
  188.             user = tmp;
  189.     }
  190.     n = command("USER %s", user);
  191.     if (n == CONTINUE) {
  192.         if (pass == NULL)
  193.             pass = getpass("Password:");
  194.         n = command("PASS %s", pass);
  195.     }
  196.     if (n == CONTINUE) {
  197.         aflag++;
  198.         acct = getpass("Account:");
  199.         n = command("ACCT %s", acct);
  200.     }
  201.     if (n != COMPLETE) {
  202.         fprintf(stderr, "Login failed.\n");
  203.         return (0);
  204.     }
  205.     if (!aflag && acct != NULL)
  206.         (void) command("ACCT %s", acct);
  207.     if (proxy)
  208.         return(1);
  209.     for (n = 0; n < macnum; ++n) {
  210.         if (!strcmp("init", macros[n].mac_name)) {
  211.             (void) strcpy(line, "$init");
  212.             makeargv();
  213.             domacro(margc, margv);
  214.             break;
  215.         }
  216.     }
  217.     return (1);
  218. }
  219.  
  220. cmdabort()
  221. {
  222.     extern jmp_buf ptabort;
  223.  
  224.     printf("\n");
  225.     (void) fflush(stdout);
  226.     abrtflag++;
  227.     if (ptflag)
  228.         longjmp(ptabort,1);
  229. }
  230.  
  231. /*VARARGS1*/
  232. command(va_alist)
  233.     va_dcl    /* Format string followed by zero or more arguments. */
  234. {
  235.     char *fmt;
  236.     va_list args;
  237.     int r, (*oldintr)(), cmdabort();
  238.  
  239.     va_start(args);
  240.     fmt = va_arg(args, char *);
  241.  
  242.     abrtflag = 0;
  243.     if (debug) {
  244.         printf("---> ");
  245.         (void) vfprintf(stdout, fmt, args);
  246.         printf("\n");
  247.         (void) fflush(stdout);
  248.     }
  249.     if (cout == NULL) {
  250.         perror ("No control connection for command");
  251.         code = -1;
  252.         return (0);
  253.     }
  254.     oldintr = signal(SIGINT,cmdabort);
  255.     (void) vfprintf(cout, fmt, args);
  256.     fprintf(cout, "\r\n");
  257.     (void) fflush(cout);
  258.     cpend = 1;
  259.     r = getreply(!strcmp(fmt, "QUIT"));
  260.     if (abrtflag && oldintr != SIG_IGN)
  261.         (*oldintr)();
  262.     (void) signal(SIGINT, oldintr);
  263.     return(r);
  264. }
  265.  
  266. char reply_string[BUFSIZ];
  267.  
  268. #include <ctype.h>
  269.  
  270. getreply(expecteof)
  271.     int expecteof;
  272. {
  273.     register int c, n;
  274.     register int dig;
  275.     register char *cp;
  276.     int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort();
  277.     int pflag = 0;
  278.     char *pt = pasv;
  279.  
  280.     cp = reply_string;
  281.     oldintr = signal(SIGINT,cmdabort);
  282.     for (;;) {
  283.         dig = n = code = 0;
  284.         while ((c = getc(cin)) != '\n') {
  285.             if (c == IAC) {     /* handle telnet commands */
  286.                 switch (c = getc(cin)) {
  287.                 case WILL:
  288.                 case WONT:
  289.                     c = getc(cin);
  290.                     fprintf(cout, "%c%c%c",IAC,DONT,c);
  291.                     (void) fflush(cout);
  292.                     break;
  293.                 case DO:
  294.                 case DONT:
  295.                     c = getc(cin);
  296.                     fprintf(cout, "%c%c%c",IAC,WONT,c);
  297.                     (void) fflush(cout);
  298.                     break;
  299.                 default:
  300.                     break;
  301.                 }
  302.                 continue;
  303.             }
  304.             dig++;
  305.             if (c == EOF) {
  306.                 if (expecteof) {
  307.                     (void) signal(SIGINT,oldintr);
  308.                     code = 221;
  309.                     return (0);
  310.                 }
  311.                 lostpeer();
  312.                 if (verbose) {
  313.                     printf("421 Service not available, remote server has closed connection\n");
  314.                     (void) fflush(stdout);
  315.                 }
  316.                 code = 421;
  317.                 return(4);
  318.             }
  319.             if (c != '\r' && (verbose > 0 ||
  320.                 (verbose > -1 && n == '5' && dig > 4))) {
  321.                 if (proxflag &&
  322.                    (dig == 1 || dig == 5 && verbose == 0))
  323.                     printf("%s:",hostname);
  324.                 (void) putchar(c);
  325.             }
  326.             if (dig < 4 && isdigit(c))
  327.                 code = code * 10 + (c - '0');
  328.             if (!pflag && code == 227)
  329.                 pflag = 1;
  330.             if (dig > 4 && pflag == 1 && isdigit(c))
  331.                 pflag = 2;
  332.             if (pflag == 2) {
  333.                 if (c != '\r' && c != ')')
  334.                     *pt++ = c;
  335.                 else {
  336.                     *pt = '\0';
  337.                     pflag = 3;
  338.                 }
  339.             }
  340.             if (dig == 4 && c == '-') {
  341.                 if (continuation)
  342.                     code = 0;
  343.                 continuation++;
  344.             }
  345.             if (n == 0)
  346.                 n = c;
  347.             *cp++ = c;
  348.         }
  349.         if (verbose > 0 || verbose > -1 && n == '5') {
  350.             (void) putchar(c);
  351.             (void) fflush (stdout);
  352.         }
  353.         if (continuation && code != originalcode) {
  354.             if (originalcode == 0)
  355.                 originalcode = code;
  356.             continue;
  357.         }
  358.         *cp = '\0';
  359.         if (n != '1')
  360.             cpend = 0;
  361.         (void) signal(SIGINT,oldintr);
  362.         if (code == 421 || originalcode == 421)
  363.             lostpeer();
  364.         if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
  365.             (*oldintr)();
  366.         return (n - '0');
  367.     }
  368. }
  369.  
  370. empty(mask, sec)
  371.     struct fd_set *mask;
  372.     int sec;
  373. {
  374.     struct timeval t;
  375.  
  376.     t.tv_sec = (long) sec;
  377.     t.tv_usec = 0;
  378.     return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
  379. }
  380.  
  381. jmp_buf    sendabort;
  382.  
  383. abortsend()
  384. {
  385.  
  386.     mflag = 0;
  387.     abrtflag = 0;
  388.     printf("\nsend aborted\n");
  389.     (void) fflush(stdout);
  390.     longjmp(sendabort, 1);
  391. }
  392.  
  393. #define HASHBYTES 1024
  394.  
  395. sendrequest(cmd, local, remote, printnames)
  396.     char *cmd, *local, *remote;
  397.     int printnames;
  398. {
  399.     FILE *fin, *dout = 0, *popen();
  400.     int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)();
  401.     int abortsend();
  402.     char buf[BUFSIZ], *bufp;
  403.     long bytes = 0, hashbytes = HASHBYTES;
  404.     register int c, d;
  405.     struct stat st;
  406.     struct timeval start, stop;
  407.     char *mode;
  408.  
  409.     if (verbose && printnames) {
  410.         if (local && *local != '-')
  411.             printf("local: %s ", local);
  412.         if (remote)
  413.             printf("remote: %s\n", remote);
  414.     }
  415.     if (proxy) {
  416.         proxtrans(cmd, local, remote);
  417.         return;
  418.     }
  419.     closefunc = NULL;
  420.     oldintr = NULL;
  421.     oldintp = NULL;
  422.     mode = "w";
  423.     if (setjmp(sendabort)) {
  424.         while (cpend) {
  425.             (void) getreply(0);
  426.         }
  427.         if (data >= 0) {
  428.             (void) close(data);
  429.             data = -1;
  430.         }
  431.         if (oldintr)
  432.             (void) signal(SIGINT,oldintr);
  433.         if (oldintp)
  434.             (void) signal(SIGPIPE,oldintp);
  435.         code = -1;
  436.         return;
  437.     }
  438.     oldintr = signal(SIGINT, abortsend);
  439.     if (strcmp(local, "-") == 0)
  440.         fin = stdin;
  441.     else if (*local == '|') {
  442.         oldintp = signal(SIGPIPE,SIG_IGN);
  443.         fin = popen(local + 1, "r");
  444.         if (fin == NULL) {
  445.             perror(local + 1);
  446.             (void) signal(SIGINT, oldintr);
  447.             (void) signal(SIGPIPE, oldintp);
  448.             code = -1;
  449.             return;
  450.         }
  451.         closefunc = pclose;
  452.     } else {
  453.         fin = fopen(local, "r");
  454.         if (fin == NULL) {
  455.             perror(local);
  456.             (void) signal(SIGINT, oldintr);
  457.             code = -1;
  458.             return;
  459.         }
  460.         closefunc = fclose;
  461.         if (fstat(fileno(fin), &st) < 0 ||
  462.             (st.st_mode&S_IFMT) != S_IFREG) {
  463.             fprintf(stdout, "%s: not a plain file.\n", local);
  464.             (void) signal(SIGINT, oldintr);
  465.             fclose(fin);
  466.             code = -1;
  467.             return;
  468.         }
  469.     }
  470.     if (initconn()) {
  471.         (void) signal(SIGINT, oldintr);
  472.         if (oldintp)
  473.             (void) signal(SIGPIPE, oldintp);
  474.         code = -1;
  475.         if (closefunc != NULL)
  476.             (*closefunc)(fin);
  477.         return;
  478.     }
  479.     if (setjmp(sendabort))
  480.         goto abort;
  481.  
  482.     if (restart_point &&
  483.         (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
  484.         if (fseek(fin, (long) restart_point, 0) < 0) {
  485.             perror(local);
  486.             restart_point = 0;
  487.             if (closefunc != NULL)
  488.                 (*closefunc)(fin);
  489.             return;
  490.         }
  491.         if (command("REST %ld", (long) restart_point)
  492.             != CONTINUE) {
  493.             restart_point = 0;
  494.             if (closefunc != NULL)
  495.                 (*closefunc)(fin);
  496.             return;
  497.         }
  498.         restart_point = 0;
  499.         mode = "r+w";
  500.     }
  501.     if (remote) {
  502.         if (command("%s %s", cmd, remote) != PRELIM) {
  503.             (void) signal(SIGINT, oldintr);
  504.             if (oldintp)
  505.                 (void) signal(SIGPIPE, oldintp);
  506.             if (closefunc != NULL)
  507.                 (*closefunc)(fin);
  508.             return;
  509.         }
  510.     } else
  511.         if (command("%s", cmd) != PRELIM) {
  512.             (void) signal(SIGINT, oldintr);
  513.             if (oldintp)
  514.                 (void) signal(SIGPIPE, oldintp);
  515.             if (closefunc != NULL)
  516.                 (*closefunc)(fin);
  517.             return;
  518.         }
  519.     dout = dataconn(mode);
  520.     if (dout == NULL)
  521.         goto abort;
  522.     (void) gettimeofday(&start, (struct timezone *)0);
  523.     oldintp = signal(SIGPIPE, SIG_IGN);
  524.     switch (type) {
  525.  
  526.     case TYPE_I:
  527.     case TYPE_L:
  528.         errno = d = 0;
  529.         while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
  530.             bytes += c;
  531.             for (bufp = buf; c > 0; c -= d, bufp += d)
  532.                 if ((d = write(fileno(dout), bufp, c)) <= 0)
  533.                     break;
  534.             if (hash) {
  535.                 while (bytes >= hashbytes) {
  536.                     (void) putchar('#');
  537.                     hashbytes += HASHBYTES;
  538.                 }
  539.                 (void) fflush(stdout);
  540.             }
  541.         }
  542.         if (hash && bytes > 0) {
  543.             if (bytes < HASHBYTES)
  544.                 (void) putchar('#');
  545.             (void) putchar('\n');
  546.             (void) fflush(stdout);
  547.         }
  548.         if (c < 0)
  549.             perror(local);
  550.         if (d <= 0) {
  551.             if (d == 0)
  552.                 fprintf(stderr, "netout: write returned 0?\n");
  553.             else if (errno != EPIPE) 
  554.                 perror("netout");
  555.             bytes = -1;
  556.         }
  557.         break;
  558.  
  559.     case TYPE_A:
  560.         while ((c = getc(fin)) != EOF) {
  561.             if (c == '\n') {
  562.                 while (hash && (bytes >= hashbytes)) {
  563.                     (void) putchar('#');
  564.                     (void) fflush(stdout);
  565.                     hashbytes += HASHBYTES;
  566.                 }
  567.                 if (ferror(dout))
  568.                     break;
  569.                 (void) putc('\r', dout);
  570.                 bytes++;
  571.             }
  572.             (void) putc(c, dout);
  573.             bytes++;
  574.     /*        if (c == '\r') {                  */
  575.     /*        (void)    putc('\0', dout);  /* this violates rfc */
  576.     /*            bytes++;                */
  577.     /*        }                                      */    
  578.         }
  579.         if (hash) {
  580.             if (bytes < hashbytes)
  581.                 (void) putchar('#');
  582.             (void) putchar('\n');
  583.             (void) fflush(stdout);
  584.         }
  585.         if (ferror(fin))
  586.             perror(local);
  587.         if (ferror(dout)) {
  588.             if (errno != EPIPE)
  589.                 perror("netout");
  590.             bytes = -1;
  591.         }
  592.         break;
  593.     }
  594.     (void) gettimeofday(&stop, (struct timezone *)0);
  595.     if (closefunc != NULL)
  596.         (*closefunc)(fin);
  597.     (void) fclose(dout);
  598.     (void) getreply(0);
  599.     (void) signal(SIGINT, oldintr);
  600.     if (oldintp)
  601.         (void) signal(SIGPIPE, oldintp);
  602.     if (bytes > 0)
  603.         ptransfer("sent", bytes, &start, &stop);
  604.     return;
  605. abort:
  606.     (void) gettimeofday(&stop, (struct timezone *)0);
  607.     (void) signal(SIGINT, oldintr);
  608.     if (oldintp)
  609.         (void) signal(SIGPIPE, oldintp);
  610.     if (!cpend) {
  611.         code = -1;
  612.         return;
  613.     }
  614.     if (data >= 0) {
  615.         (void) close(data);
  616.         data = -1;
  617.     }
  618.     if (dout)
  619.         (void) fclose(dout);
  620.     (void) getreply(0);
  621.     code = -1;
  622.     if (closefunc != NULL && fin != NULL)
  623.         (*closefunc)(fin);
  624.     if (bytes > 0)
  625.         ptransfer("sent", bytes, &start, &stop);
  626. }
  627.  
  628. jmp_buf    recvabort;
  629.  
  630. abortrecv()
  631. {
  632.  
  633.     mflag = 0;
  634.     abrtflag = 0;
  635.     printf("\n");
  636.     (void) fflush(stdout);
  637.     longjmp(recvabort, 1);
  638. }
  639.  
  640. recvrequest(cmd, local, remote, mode, printnames)
  641.     char *cmd, *local, *remote, *mode;
  642. {
  643.     FILE *fout, *din = 0, *popen();
  644.     int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); 
  645.     int abortrecv(), oldverbose, oldtype = 0, is_retr, tcrflag, nfnd;
  646.     char *bufp, *gunique(), msg;
  647.     static char *buf;
  648.     static int bufsize;
  649.     long bytes = 0, hashbytes = HASHBYTES;
  650.     struct fd_set mask;
  651.     register int c, d;
  652.     struct timeval start, stop;
  653.     struct stat st;
  654.     extern char *malloc();
  655.  
  656.     is_retr = strcmp(cmd, "RETR") == 0;
  657.     if (is_retr && verbose && printnames) {
  658.         if (local && *local != '-')
  659.             printf("local: %s ", local);
  660.         if (remote)
  661.             printf("remote: %s\n", remote);
  662.     }
  663.     if (proxy && is_retr) {
  664.         proxtrans(cmd, local, remote);
  665.         return;
  666.     }
  667.     closefunc = NULL;
  668.     oldintr = NULL;
  669.     oldintp = NULL;
  670.     tcrflag = !crflag && is_retr;
  671.     if (setjmp(recvabort)) {
  672.         while (cpend) {
  673.             (void) getreply(0);
  674.         }
  675.         if (data >= 0) {
  676.             (void) close(data);
  677.             data = -1;
  678.         }
  679.         if (oldintr)
  680.             (void) signal(SIGINT, oldintr);
  681.         code = -1;
  682.         return;
  683.     }
  684.     oldintr = signal(SIGINT, abortrecv);
  685.     if (strcmp(local, "-") && *local != '|') {
  686.         if (access(local, 2) < 0) {
  687.             char *dir = rindex(local, '/');
  688.  
  689.             if (errno != ENOENT && errno != EACCES) {
  690.                 perror(local);
  691.                 (void) signal(SIGINT, oldintr);
  692.                 code = -1;
  693.                 return;
  694.             }
  695.             if (dir != NULL)
  696.                 *dir = 0;
  697.             d = access(dir ? local : ".", 2);
  698.             if (dir != NULL)
  699.                 *dir = '/';
  700.             if (d < 0) {
  701.                 perror(local);
  702.                 (void) signal(SIGINT, oldintr);
  703.                 code = -1;
  704.                 return;
  705.             }
  706.             if (!runique && errno == EACCES &&
  707.                 chmod(local, 0600) < 0) {
  708.                 perror(local);
  709.                 (void) signal(SIGINT, oldintr);
  710.                 code = -1;
  711.                 return;
  712.             }
  713.             if (runique && errno == EACCES &&
  714.                (local = gunique(local)) == NULL) {
  715.                 (void) signal(SIGINT, oldintr);
  716.                 code = -1;
  717.                 return;
  718.             }
  719.         }
  720.         else if (runique && (local = gunique(local)) == NULL) {
  721.             (void) signal(SIGINT, oldintr);
  722.             code = -1;
  723.             return;
  724.         }
  725.     }
  726.     if (initconn()) {
  727.         (void) signal(SIGINT, oldintr);
  728.         code = -1;
  729.         return;
  730.     }
  731.     if (setjmp(recvabort))
  732.         goto abort;
  733.     if (!is_retr) {
  734.         if (type != TYPE_A) {
  735.             oldtype = type;
  736.             oldverbose = verbose;
  737.             if (!debug)
  738.                 verbose = 0;
  739.             setascii();
  740.             verbose = oldverbose;
  741.         }
  742.     } else if (restart_point) {
  743.         if (command("REST %ld", (long) restart_point) != CONTINUE)
  744.             return;
  745.     }
  746.     if (remote) {
  747.         if (command("%s %s", cmd, remote) != PRELIM) {
  748.             (void) signal(SIGINT, oldintr);
  749.             if (oldtype) {
  750.                 if (!debug)
  751.                     verbose = 0;
  752.                 switch (oldtype) {
  753.                     case TYPE_I:
  754.                         setbinary();
  755.                         break;
  756.                     case TYPE_E:
  757.                         setebcdic();
  758.                         break;
  759.                     case TYPE_L:
  760.                         settenex();
  761.                         break;
  762.                 }
  763.                 verbose = oldverbose;
  764.             }
  765.             return;
  766.         }
  767.     } else {
  768.         if (command("%s", cmd) != PRELIM) {
  769.             (void) signal(SIGINT, oldintr);
  770.             if (oldtype) {
  771.                 if (!debug)
  772.                     verbose = 0;
  773.                 switch (oldtype) {
  774.                     case TYPE_I:
  775.                         setbinary();
  776.                         break;
  777.                     case TYPE_E:
  778.                         setebcdic();
  779.                         break;
  780.                     case TYPE_L:
  781.                         settenex();
  782.                         break;
  783.                 }
  784.                 verbose = oldverbose;
  785.             }
  786.             return;
  787.         }
  788.     }
  789.     din = dataconn("r");
  790.     if (din == NULL)
  791.         goto abort;
  792.     if (strcmp(local, "-") == 0)
  793.         fout = stdout;
  794.     else if (*local == '|') {
  795.         oldintp = signal(SIGPIPE, SIG_IGN);
  796.         fout = popen(local + 1, "w");
  797.         if (fout == NULL) {
  798.             perror(local+1);
  799.             goto abort;
  800.         }
  801.         closefunc = pclose;
  802.     } else {
  803.         fout = fopen(local, mode);
  804.         if (fout == NULL) {
  805.             perror(local);
  806.             goto abort;
  807.         }
  808.         closefunc = fclose;
  809.     }
  810.     if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
  811.         st.st_blksize = BUFSIZ;
  812.     if (st.st_blksize > bufsize) {
  813.         if (buf)
  814.             (void) free(buf);
  815.         buf = malloc(st.st_blksize);
  816.         if (buf == NULL) {
  817.             perror("malloc");
  818.             bufsize = 0;
  819.             goto abort;
  820.         }
  821.         bufsize = st.st_blksize;
  822.     }
  823.     (void) gettimeofday(&start, (struct timezone *)0);
  824.     switch (type) {
  825.  
  826.     case TYPE_I:
  827.     case TYPE_L:
  828.         if (restart_point &&
  829.             lseek(fileno(fout), (long) restart_point, L_SET) < 0) {
  830.             perror(local);
  831.             if (closefunc != NULL)
  832.                 (*closefunc)(fout);
  833.             return;
  834.         }
  835.         errno = d = 0;
  836.         while ((c = read(fileno(din), buf, bufsize)) > 0) {
  837.             if ((d = write(fileno(fout), buf, c)) != c)
  838.                 break;
  839.             bytes += c;
  840.             if (hash) {
  841.                 while (bytes >= hashbytes) {
  842.                     (void) putchar('#');
  843.                     hashbytes += HASHBYTES;
  844.                 }
  845.                 (void) fflush(stdout);
  846.             }
  847.         }
  848.         if (hash && bytes > 0) {
  849.             if (bytes < HASHBYTES)
  850.                 (void) putchar('#');
  851.             (void) putchar('\n');
  852.             (void) fflush(stdout);
  853.         }
  854.         if (c < 0) {
  855.             if (errno != EPIPE)
  856.                 perror("netin");
  857.             bytes = -1;
  858.         }
  859.         if (d < c) {
  860.             if (d < 0)
  861.                 perror(local);
  862.             else
  863.                 fprintf(stderr, "%s: short write\n", local);
  864.         }
  865.         break;
  866.  
  867.     case TYPE_A:
  868.         if (restart_point) {
  869.             register int i, n, c;
  870.  
  871.             if (fseek(fout, 0L, L_SET) < 0)
  872.                 goto done;
  873.             n = restart_point;
  874.             i = 0;
  875.             while (i++ < n) {
  876.                 if ((c=getc(fout)) == EOF)
  877.                     goto done;
  878.                 if (c == '\n')
  879.                     i++;
  880.             }
  881.             if (fseek(fout, 0L, L_INCR) < 0) {
  882. done:
  883.                 perror(local);
  884.                 if (closefunc != NULL)
  885.                     (*closefunc)(fout);
  886.                 return;
  887.             }
  888.         }
  889.         while ((c = getc(din)) != EOF) {
  890.             while (c == '\r') {
  891.                 while (hash && (bytes >= hashbytes)) {
  892.                     (void) putchar('#');
  893.                     (void) fflush(stdout);
  894.                     hashbytes += HASHBYTES;
  895.                 }
  896.                 bytes++;
  897.                 if ((c = getc(din)) != '\n' || tcrflag) {
  898.                     if (ferror(fout))
  899.                         goto break2;
  900.                     (void) putc('\r', fout);
  901.                     if (c == '\0') {
  902.                         bytes++;
  903.                         goto contin2;
  904.                     }
  905.                     if (c == EOF)
  906.                         goto contin2;
  907.                 }
  908.             }
  909.             (void) putc(c, fout);
  910.             bytes++;
  911.     contin2:    ;
  912.         }
  913. break2:
  914.         if (hash) {
  915.             if (bytes < hashbytes)
  916.                 (void) putchar('#');
  917.             (void) putchar('\n');
  918.             (void) fflush(stdout);
  919.         }
  920.         if (ferror(din)) {
  921.             if (errno != EPIPE)
  922.                 perror("netin");
  923.             bytes = -1;
  924.         }
  925.         if (ferror(fout))
  926.             perror(local);
  927.         break;
  928.     }
  929.     if (closefunc != NULL)
  930.         (*closefunc)(fout);
  931.     (void) signal(SIGINT, oldintr);
  932.     if (oldintp)
  933.         (void) signal(SIGPIPE, oldintp);
  934.     (void) gettimeofday(&stop, (struct timezone *)0);
  935.     (void) fclose(din);
  936.     (void) getreply(0);
  937.     if (bytes > 0 && is_retr)
  938.         ptransfer("received", bytes, &start, &stop);
  939.     if (oldtype) {
  940.         if (!debug)
  941.             verbose = 0;
  942.         switch (oldtype) {
  943.             case TYPE_I:
  944.                 setbinary();
  945.                 break;
  946.             case TYPE_E:
  947.                 setebcdic();
  948.                 break;
  949.             case TYPE_L:
  950.                 settenex();
  951.                 break;
  952.         }
  953.         verbose = oldverbose;
  954.     }
  955.     return;
  956. abort:
  957.  
  958. /* abort using RFC959 recommended IP,SYNC sequence  */
  959.  
  960.     (void) gettimeofday(&stop, (struct timezone *)0);
  961.     if (oldintp)
  962.         (void) signal(SIGPIPE, oldintr);
  963.     (void) signal(SIGINT,SIG_IGN);
  964.     if (oldtype) {
  965.         if (!debug)
  966.             verbose = 0;
  967.         switch (oldtype) {
  968.             case TYPE_I:
  969.                 setbinary();
  970.                 break;
  971.             case TYPE_E:
  972.                 setebcdic();
  973.                 break;
  974.             case TYPE_L:
  975.                 settenex();
  976.                 break;
  977.         }
  978.         verbose = oldverbose;
  979.     }
  980.     if (!cpend) {
  981.         code = -1;
  982.         (void) signal(SIGINT,oldintr);
  983.         return;
  984.     }
  985.  
  986.     fprintf(cout,"%c%c",IAC,IP);
  987.     (void) fflush(cout); 
  988.     msg = IAC;
  989. /* send IAC in urgent mode instead of DM because UNIX places oob mark */
  990. /* after urgent byte rather than before as now is protocol            */
  991.     if (send(fileno(cout),&msg,1,MSG_OOB) != 1) {
  992.         perror("abort");
  993.     }
  994.     fprintf(cout,"%cABOR\r\n",DM);
  995.     (void) fflush(cout);
  996.     FD_ZERO(&mask);
  997.     FD_SET(fileno(cin), &mask);
  998.     if (din) { 
  999.         FD_SET(fileno(din), &mask);
  1000.     }
  1001.     if ((nfnd = empty(&mask,10)) <= 0) {
  1002.         if (nfnd < 0) {
  1003.             perror("abort");
  1004.         }
  1005.         code = -1;
  1006.         lostpeer();
  1007.     }
  1008.     if (din && FD_ISSET(fileno(din), &mask)) {
  1009.         while ((c = read(fileno(din), buf, bufsize)) > 0)
  1010.             ;
  1011.     }
  1012.     if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */
  1013.         if (data >= 0) {
  1014.             (void) close(data);
  1015.             data = -1;
  1016.         }
  1017.         (void) getreply(0);
  1018.     }
  1019.     (void) getreply(0);
  1020.     code = -1;
  1021.     if (data >= 0) {
  1022.         (void) close(data);
  1023.         data = -1;
  1024.     }
  1025.     if (closefunc != NULL && fout != NULL)
  1026.         (*closefunc)(fout);
  1027.     if (din)
  1028.         (void) fclose(din);
  1029.     if (bytes > 0)
  1030.         ptransfer("received", bytes, &start, &stop);
  1031.     (void) signal(SIGINT,oldintr);
  1032. }
  1033.  
  1034. /*
  1035.  * Need to start a listen on the data channel
  1036.  * before we send the command, otherwise the
  1037.  * server's connect may fail.
  1038.  */
  1039. int sendport = -1;
  1040.  
  1041. initconn()
  1042. {
  1043.     register char *p, *a;
  1044.     int result, len, tmpno = 0;
  1045.     int on = 1;
  1046.  
  1047. noport:
  1048.     data_addr = myctladdr;
  1049.     if (sendport)
  1050.         data_addr.sin_port = 0;    /* let system pick one */ 
  1051.     if (data != -1)
  1052.         (void) close (data);
  1053.     data = socket(AF_INET, SOCK_STREAM, 0);
  1054.     if (data < 0) {
  1055.         perror("ftp: socket");
  1056.         if (tmpno)
  1057.             sendport = 1;
  1058.         return (1);
  1059.     }
  1060.     if (!sendport)
  1061.         if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
  1062.             perror("ftp: setsockopt (reuse address)");
  1063.             goto bad;
  1064.         }
  1065.     if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
  1066.         perror("ftp: bind");
  1067.         goto bad;
  1068.     }
  1069.     if (options & SO_DEBUG &&
  1070.         setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
  1071.         perror("ftp: setsockopt (ignored)");
  1072.     len = sizeof (data_addr);
  1073.     if (getsockname(data, (char *)&data_addr, &len) < 0) {
  1074.         perror("ftp: getsockname");
  1075.         goto bad;
  1076.     }
  1077.     if (listen(data, 1) < 0)
  1078.         perror("ftp: listen");
  1079.     if (sendport) {
  1080.         a = (char *)&data_addr.sin_addr;
  1081.         p = (char *)&data_addr.sin_port;
  1082. #define    UC(b)    (((int)b)&0xff)
  1083.         result =
  1084.             command("PORT %d,%d,%d,%d,%d,%d",
  1085.               UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
  1086.               UC(p[0]), UC(p[1]));
  1087.         if (result == ERROR && sendport == -1) {
  1088.             sendport = 0;
  1089.             tmpno = 1;
  1090.             goto noport;
  1091.         }
  1092.         return (result != COMPLETE);
  1093.     }
  1094.     if (tmpno)
  1095.         sendport = 1;
  1096.     return (0);
  1097. bad:
  1098.     (void) close(data), data = -1;
  1099.     if (tmpno)
  1100.         sendport = 1;
  1101.     return (1);
  1102. }
  1103.  
  1104. FILE *
  1105. dataconn(mode)
  1106.     char *mode;
  1107. {
  1108.     struct sockaddr_in from;
  1109.     int s, fromlen = sizeof (from);
  1110.  
  1111.     s = accept(data, (struct sockaddr *) &from, &fromlen);
  1112.     if (s < 0) {
  1113.         perror("ftp: accept");
  1114.         (void) close(data), data = -1;
  1115.         return (NULL);
  1116.     }
  1117.     (void) close(data);
  1118.     data = s;
  1119.     return (fdopen(data, mode));
  1120. }
  1121.  
  1122. ptransfer(direction, bytes, t0, t1)
  1123.     char *direction;
  1124.     long bytes;
  1125.     struct timeval *t0, *t1;
  1126. {
  1127.     struct timeval td;
  1128.     float s, bs;
  1129.  
  1130.     if (verbose) {
  1131.         tvsub(&td, t1, t0);
  1132.         s = td.tv_sec + (td.tv_usec / 1000000.);
  1133. #define    nz(x)    ((x) == 0 ? 1 : (x))
  1134.         bs = bytes / nz(s);
  1135.         printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n",
  1136.             bytes, direction, s, bs / 1024.);
  1137.     }
  1138. }
  1139.  
  1140. /*tvadd(tsum, t0)
  1141.     struct timeval *tsum, *t0;
  1142. {
  1143.  
  1144.     tsum->tv_sec += t0->tv_sec;
  1145.     tsum->tv_usec += t0->tv_usec;
  1146.     if (tsum->tv_usec > 1000000)
  1147.         tsum->tv_sec++, tsum->tv_usec -= 1000000;
  1148. } */
  1149.  
  1150. tvsub(tdiff, t1, t0)
  1151.     struct timeval *tdiff, *t1, *t0;
  1152. {
  1153.  
  1154.     tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
  1155.     tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
  1156.     if (tdiff->tv_usec < 0)
  1157.         tdiff->tv_sec--, tdiff->tv_usec += 1000000;
  1158. }
  1159.  
  1160. psabort()
  1161. {
  1162.     extern int abrtflag;
  1163.  
  1164.     abrtflag++;
  1165. }
  1166.  
  1167. pswitch(flag)
  1168.     int flag;
  1169. {
  1170.     extern int proxy, abrtflag;
  1171.     int (*oldintr)();
  1172.     static struct comvars {
  1173.         int connect;
  1174.         char name[MAXHOSTNAMELEN];
  1175.         struct sockaddr_in mctl;
  1176.         struct sockaddr_in hctl;
  1177.         FILE *in;
  1178.         FILE *out;
  1179.         int tpe;
  1180.         int cpnd;
  1181.         int sunqe;
  1182.         int runqe;
  1183.         int mcse;
  1184.         int ntflg;
  1185.         char nti[17];
  1186.         char nto[17];
  1187.         int mapflg;
  1188.         char mi[MAXPATHLEN];
  1189.         char mo[MAXPATHLEN];
  1190.         } proxstruct, tmpstruct;
  1191.     struct comvars *ip, *op;
  1192.  
  1193.     abrtflag = 0;
  1194.     oldintr = signal(SIGINT, psabort);
  1195.     if (flag) {
  1196.         if (proxy)
  1197.             return;
  1198.         ip = &tmpstruct;
  1199.         op = &proxstruct;
  1200.         proxy++;
  1201.     }
  1202.     else {
  1203.         if (!proxy)
  1204.             return;
  1205.         ip = &proxstruct;
  1206.         op = &tmpstruct;
  1207.         proxy = 0;
  1208.     }
  1209.     ip->connect = connected;
  1210.     connected = op->connect;
  1211.     if (hostname) {
  1212.         (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
  1213.         ip->name[strlen(ip->name)] = '\0';
  1214.     } else
  1215.         ip->name[0] = 0;
  1216.     hostname = op->name;
  1217.     ip->hctl = hisctladdr;
  1218.     hisctladdr = op->hctl;
  1219.     ip->mctl = myctladdr;
  1220.     myctladdr = op->mctl;
  1221.     ip->in = cin;
  1222.     cin = op->in;
  1223.     ip->out = cout;
  1224.     cout = op->out;
  1225.     ip->tpe = type;
  1226.     type = op->tpe;
  1227.     if (!type)
  1228.         type = 1;
  1229.     ip->cpnd = cpend;
  1230.     cpend = op->cpnd;
  1231.     ip->sunqe = sunique;
  1232.     sunique = op->sunqe;
  1233.     ip->runqe = runique;
  1234.     runique = op->runqe;
  1235.     ip->mcse = mcase;
  1236.     mcase = op->mcse;
  1237.     ip->ntflg = ntflag;
  1238.     ntflag = op->ntflg;
  1239.     (void) strncpy(ip->nti, ntin, 16);
  1240.     (ip->nti)[strlen(ip->nti)] = '\0';
  1241.     (void) strcpy(ntin, op->nti);
  1242.     (void) strncpy(ip->nto, ntout, 16);
  1243.     (ip->nto)[strlen(ip->nto)] = '\0';
  1244.     (void) strcpy(ntout, op->nto);
  1245.     ip->mapflg = mapflag;
  1246.     mapflag = op->mapflg;
  1247.     (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
  1248.     (ip->mi)[strlen(ip->mi)] = '\0';
  1249.     (void) strcpy(mapin, op->mi);
  1250.     (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
  1251.     (ip->mo)[strlen(ip->mo)] = '\0';
  1252.     (void) strcpy(mapout, op->mo);
  1253.     (void) signal(SIGINT, oldintr);
  1254.     if (abrtflag) {
  1255.         abrtflag = 0;
  1256.         (*oldintr)();
  1257.     }
  1258. }
  1259.  
  1260. jmp_buf ptabort;
  1261. int ptabflg;
  1262.  
  1263. abortpt()
  1264. {
  1265.     printf("\n");
  1266.     (void) fflush(stdout);
  1267.     ptabflg++;
  1268.     mflag = 0;
  1269.     abrtflag = 0;
  1270.     longjmp(ptabort, 1);
  1271. }
  1272.  
  1273. proxtrans(cmd, local, remote)
  1274.     char *cmd, *local, *remote;
  1275. {
  1276.     int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0, nfnd;
  1277.     extern jmp_buf ptabort;
  1278.     char *cmd2;
  1279.     struct fd_set mask;
  1280.  
  1281.     if (strcmp(cmd, "RETR"))
  1282.         cmd2 = "RETR";
  1283.     else
  1284.         cmd2 = runique ? "STOU" : "STOR";
  1285.     if (command("PASV") != COMPLETE) {
  1286.         printf("proxy server does not support third part transfers.\n");
  1287.         return;
  1288.     }
  1289.     tmptype = type;
  1290.     pswitch(0);
  1291.     if (!connected) {
  1292.         printf("No primary connection\n");
  1293.         pswitch(1);
  1294.         code = -1;
  1295.         return;
  1296.     }
  1297.     if (type != tmptype) {
  1298.         oldtype = type;
  1299.         switch (tmptype) {
  1300.             case TYPE_A:
  1301.                 setascii();
  1302.                 break;
  1303.             case TYPE_I:
  1304.                 setbinary();
  1305.                 break;
  1306.             case TYPE_E:
  1307.                 setebcdic();
  1308.                 break;
  1309.             case TYPE_L:
  1310.                 settenex();
  1311.                 break;
  1312.         }
  1313.     }
  1314.     if (command("PORT %s", pasv) != COMPLETE) {
  1315.         switch (oldtype) {
  1316.             case 0:
  1317.                 break;
  1318.             case TYPE_A:
  1319.                 setascii();
  1320.                 break;
  1321.             case TYPE_I:
  1322.                 setbinary();
  1323.                 break;
  1324.             case TYPE_E:
  1325.                 setebcdic();
  1326.                 break;
  1327.             case TYPE_L:
  1328.                 settenex();
  1329.                 break;
  1330.         }
  1331.         pswitch(1);
  1332.         return;
  1333.     }
  1334.     if (setjmp(ptabort))
  1335.         goto abort;
  1336.     oldintr = signal(SIGINT, abortpt);
  1337.     if (command("%s %s", cmd, remote) != PRELIM) {
  1338.         (void) signal(SIGINT, oldintr);
  1339.         switch (oldtype) {
  1340.             case 0:
  1341.                 break;
  1342.             case TYPE_A:
  1343.                 setascii();
  1344.                 break;
  1345.             case TYPE_I:
  1346.                 setbinary();
  1347.                 break;
  1348.             case TYPE_E:
  1349.                 setebcdic();
  1350.                 break;
  1351.             case TYPE_L:
  1352.                 settenex();
  1353.                 break;
  1354.         }
  1355.         pswitch(1);
  1356.         return;
  1357.     }
  1358.     sleep(2);
  1359.     pswitch(1);
  1360.     secndflag++;
  1361.     if (command("%s %s", cmd2, local) != PRELIM)
  1362.         goto abort;
  1363.     ptflag++;
  1364.     (void) getreply(0);
  1365.     pswitch(0);
  1366.     (void) getreply(0);
  1367.     (void) signal(SIGINT, oldintr);
  1368.     switch (oldtype) {
  1369.         case 0:
  1370.             break;
  1371.         case TYPE_A:
  1372.             setascii();
  1373.             break;
  1374.         case TYPE_I:
  1375.             setbinary();
  1376.             break;
  1377.         case TYPE_E:
  1378.             setebcdic();
  1379.             break;
  1380.         case TYPE_L:
  1381.             settenex();
  1382.             break;
  1383.     }
  1384.     pswitch(1);
  1385.     ptflag = 0;
  1386.     printf("local: %s remote: %s\n", local, remote);
  1387.     return;
  1388. abort:
  1389.     (void) signal(SIGINT, SIG_IGN);
  1390.     ptflag = 0;
  1391.     if (strcmp(cmd, "RETR") && !proxy)
  1392.         pswitch(1);
  1393.     else if (!strcmp(cmd, "RETR") && proxy)
  1394.         pswitch(0);
  1395.     if (!cpend && !secndflag) {  /* only here if cmd = "STOR" (proxy=1) */
  1396.         if (command("%s %s", cmd2, local) != PRELIM) {
  1397.             pswitch(0);
  1398.             switch (oldtype) {
  1399.                 case 0:
  1400.                     break;
  1401.                 case TYPE_A:
  1402.                     setascii();
  1403.                     break;
  1404.                 case TYPE_I:
  1405.                     setbinary();
  1406.                     break;
  1407.                 case TYPE_E:
  1408.                     setebcdic();
  1409.                     break;
  1410.                 case TYPE_L:
  1411.                     settenex();
  1412.                     break;
  1413.             }
  1414.             if (cpend) {
  1415.                 char msg[2];
  1416.  
  1417.                 fprintf(cout,"%c%c",IAC,IP);
  1418.                 (void) fflush(cout); 
  1419.                 *msg = IAC;
  1420.                 *(msg+1) = DM;
  1421.                 if (send(fileno(cout),msg,2,MSG_OOB) != 2)
  1422.                     perror("abort");
  1423.                 fprintf(cout,"ABOR\r\n");
  1424.                 (void) fflush(cout);
  1425.                 FD_ZERO(&mask);
  1426.                 FD_SET(fileno(cin), &mask);
  1427.                 if ((nfnd = empty(&mask,10)) <= 0) {
  1428.                     if (nfnd < 0) {
  1429.                         perror("abort");
  1430.                     }
  1431.                     if (ptabflg)
  1432.                         code = -1;
  1433.                     lostpeer();
  1434.                 }
  1435.                 (void) getreply(0);
  1436.                 (void) getreply(0);
  1437.             }
  1438.         }
  1439.         pswitch(1);
  1440.         if (ptabflg)
  1441.             code = -1;
  1442.         (void) signal(SIGINT, oldintr);
  1443.         return;
  1444.     }
  1445.     if (cpend) {
  1446.         char msg[2];
  1447.  
  1448.         fprintf(cout,"%c%c",IAC,IP);
  1449.         (void) fflush(cout); 
  1450.         *msg = IAC;
  1451.         *(msg+1) = DM;
  1452.         if (send(fileno(cout),msg,2,MSG_OOB) != 2)
  1453.             perror("abort");
  1454.         fprintf(cout,"ABOR\r\n");
  1455.         (void) fflush(cout);
  1456.         FD_ZERO(&mask);
  1457.         FD_SET(fileno(cin), &mask);
  1458.         if ((nfnd = empty(&mask,10)) <= 0) {
  1459.             if (nfnd < 0) {
  1460.                 perror("abort");
  1461.             }
  1462.             if (ptabflg)
  1463.                 code = -1;
  1464.             lostpeer();
  1465.         }
  1466.         (void) getreply(0);
  1467.         (void) getreply(0);
  1468.     }
  1469.     pswitch(!proxy);
  1470.     if (!cpend && !secndflag) {  /* only if cmd = "RETR" (proxy=1) */
  1471.         if (command("%s %s", cmd2, local) != PRELIM) {
  1472.             pswitch(0);
  1473.             switch (oldtype) {
  1474.                 case 0:
  1475.                     break;
  1476.                 case TYPE_A:
  1477.                     setascii();
  1478.                     break;
  1479.                 case TYPE_I:
  1480.                     setbinary();
  1481.                     break;
  1482.                 case TYPE_E:
  1483.                     setebcdic();
  1484.                     break;
  1485.                 case TYPE_L:
  1486.                     settenex();
  1487.                     break;
  1488.             }
  1489.             if (cpend) {
  1490.                 char msg[2];
  1491.  
  1492.                 fprintf(cout,"%c%c",IAC,IP);
  1493.                 (void) fflush(cout); 
  1494.                 *msg = IAC;
  1495.                 *(msg+1) = DM;
  1496.                 if (send(fileno(cout),msg,2,MSG_OOB) != 2)
  1497.                     perror("abort");
  1498.                 fprintf(cout,"ABOR\r\n");
  1499.                 (void) fflush(cout);
  1500.                 FD_ZERO(&mask);
  1501.                 FD_SET(fileno(cin), &mask);
  1502.                 if ((nfnd = empty(&mask,10)) <= 0) {
  1503.                     if (nfnd < 0) {
  1504.                         perror("abort");
  1505.                     }
  1506.                     if (ptabflg)
  1507.                         code = -1;
  1508.                     lostpeer();
  1509.                 }
  1510.                 (void) getreply(0);
  1511.                 (void) getreply(0);
  1512.             }
  1513.             pswitch(1);
  1514.             if (ptabflg)
  1515.                 code = -1;
  1516.             (void) signal(SIGINT, oldintr);
  1517.             return;
  1518.         }
  1519.     }
  1520.     if (cpend) {
  1521.         char msg[2];
  1522.  
  1523.         fprintf(cout,"%c%c",IAC,IP);
  1524.         (void) fflush(cout); 
  1525.         *msg = IAC;
  1526.         *(msg+1) = DM;
  1527.         if (send(fileno(cout),msg,2,MSG_OOB) != 2)
  1528.             perror("abort");
  1529.         fprintf(cout,"ABOR\r\n");
  1530.         (void) fflush(cout);
  1531.         FD_ZERO(&mask);
  1532.         FD_SET(fileno(cin), &mask);
  1533.         if ((nfnd = empty(&mask,10)) <= 0) {
  1534.             if (nfnd < 0) {
  1535.                 perror("abort");
  1536.             }
  1537.             if (ptabflg)
  1538.                 code = -1;
  1539.             lostpeer();
  1540.         }
  1541.         (void) getreply(0);
  1542.         (void) getreply(0);
  1543.     }
  1544.     pswitch(!proxy);
  1545.     if (cpend) {
  1546.         FD_ZERO(&mask);
  1547.         FD_SET(fileno(cin), &mask);
  1548.         if ((nfnd = empty(&mask,10)) <= 0) {
  1549.             if (nfnd < 0) {
  1550.                 perror("abort");
  1551.             }
  1552.             if (ptabflg)
  1553.                 code = -1;
  1554.             lostpeer();
  1555.         }
  1556.         (void) getreply(0);
  1557.         (void) getreply(0);
  1558.     }
  1559.     if (proxy)
  1560.         pswitch(0);
  1561.     switch (oldtype) {
  1562.         case 0:
  1563.             break;
  1564.         case TYPE_A:
  1565.             setascii();
  1566.             break;
  1567.         case TYPE_I:
  1568.             setbinary();
  1569.             break;
  1570.         case TYPE_E:
  1571.             setebcdic();
  1572.             break;
  1573.         case TYPE_L:
  1574.             settenex();
  1575.             break;
  1576.     }
  1577.     pswitch(1);
  1578.     if (ptabflg)
  1579.         code = -1;
  1580.     (void) signal(SIGINT, oldintr);
  1581. }
  1582.  
  1583. reset()
  1584. {
  1585.     struct fd_set mask;
  1586.     int nfnd = 1;
  1587.  
  1588.     FD_ZERO(&mask);
  1589.     while (nfnd > 0) {
  1590.         FD_SET(fileno(cin), &mask);
  1591.         if ((nfnd = empty(&mask,0)) < 0) {
  1592.             perror("reset");
  1593.             code = -1;
  1594.             lostpeer();
  1595.         }
  1596.         else if (nfnd) {
  1597.             (void) getreply(0);
  1598.         }
  1599.     }
  1600. }
  1601.  
  1602. char *
  1603. gunique(local)
  1604.     char *local;
  1605. {
  1606.     static char new[MAXPATHLEN];
  1607.     char *cp = rindex(local, '/');
  1608.     int d, count=0;
  1609.     char ext = '1';
  1610.  
  1611.     if (cp)
  1612.         *cp = '\0';
  1613.     d = access(cp ? local : ".", 2);
  1614.     if (cp)
  1615.         *cp = '/';
  1616.     if (d < 0) {
  1617.         perror(local);
  1618.         return((char *) 0);
  1619.     }
  1620.     (void) strcpy(new, local);
  1621.     cp = new + strlen(new);
  1622.     *cp++ = '.';
  1623.     while (!d) {
  1624.         if (++count == 100) {
  1625.             printf("runique: can't find unique file name.\n");
  1626.             return((char *) 0);
  1627.         }
  1628.         *cp++ = ext;
  1629.         *cp = '\0';
  1630.         if (ext == '9')
  1631.             ext = '0';
  1632.         else
  1633.             ext++;
  1634.         if ((d = access(new, 0)) < 0)
  1635.             break;
  1636.         if (ext != '0')
  1637.             cp--;
  1638.         else if (*(cp - 2) == '.')
  1639.             *(cp - 1) = '1';
  1640.         else {
  1641.             *(cp - 2) = *(cp - 2) + 1;
  1642.             cp--;
  1643.         }
  1644.     }
  1645.     return(new);
  1646. }
  1647.